package com.ccteam.fluidmusic.widget.comment

import android.content.Context
import android.database.Observable
import android.util.AttributeSet
import android.view.View
import android.widget.LinearLayout
import androidx.core.content.res.ResourcesCompat
import com.ccteam.fluidmusic.R
import com.ccteam.shared.result.moment.comment.MomentReplayItem
import kotlin.math.min

/**
 * @author Xiaoc
 * @since 2021/3/29
 */
class ReplyLayout @JvmOverloads constructor(
    context: Context,
    attrs: AttributeSet? = null,
    defStyleAttr: Int = 0): LinearLayout(context,attrs,defStyleAttr) {

    private var mAdapter: ReplayLayoutAdapter? = null

    /**
     * 观察器，用于Adapter通知数据变化进行操作
     */
    private val mObserver = ReplayDataObserver()

    private val replyViews: MutableList<ReplyView> = mutableListOf()

    /**
     * 图片地址列表缓存，用于缓存ImageView，以复用
     */
    private var mCacheSize: Int = 0

    init {
        orientation = VERTICAL
    }

    fun getAdapter(): ReplayLayoutAdapter?{
        return mAdapter
    }

    fun setAdapter(adapter: ReplayLayoutAdapter){
        handleAdapterInternal(adapter)
        handleReplay()
    }

    private fun handleAdapterInternal(adapter: ReplayLayoutAdapter){
        mAdapter?.unregisterAdapterDataObserver(mObserver)
        mAdapter = adapter
        adapter.registerAdapterDataObserver(mObserver)
    }

    private fun handleReplay(){
        if(mAdapter == null){
            return
        }

        val replayList = mAdapter!!.mReplayList

        val imageCount = replayList.size

        // 处理回复背景轮廓
        handleBackground(imageCount != 0)

        // 如果原来列表不为空，则进行对应的增删布局操作
        val oldViewCount = mCacheSize
        if(oldViewCount > imageCount){
            removeViews(imageCount,oldViewCount - imageCount)
        } else if(oldViewCount < imageCount){
            for(index in oldViewCount until imageCount){
                val iv = reUseReplayView(index) ?: return
                if(iv.parent != null){
                    removeView(iv)
                }
                addView(iv)
            }
        }

        mCacheSize = imageCount

        // 重新绘制布局
        requestLayout()

        // 进行内容填充
        mAdapter!!.mReplayList.forEachIndexed { index, _ ->
            val childrenView = getChildAt(index) as ReplyView
            mAdapter!!.handleReplayView(childrenView,index)
        }
    }

    /**
     * 处理背景圆角轮廓
     */
    private fun handleBackground(show: Boolean){
        background = if(show){
            ResourcesCompat.getDrawable(
                resources,R.drawable.shape_reply_bg,context.theme
            )
        } else {
            null
        }
    }

    private fun reUseReplayView(index: Int): ReplyView?{
        return if(index < replyViews.size){
            replyViews[index]
        } else {
            if(mAdapter != null){
                val replayView = mAdapter!!.generateReplayView(context)
                addView(replayView)
                return replayView
            } else {
                null
            }
        }
    }

    class ReplayLayoutAdapter(private val callback: ReplayItemCallback,
                              private val maxVisibleCount: Int = 3){

        private var shouldShowMore = false

        /**
         * 数据观察者
         */
        private val mObservable = AdapterDataObservable()

        val mReplayList: MutableList<MomentReplayItem> = mutableListOf()

        fun subReplayList(replayList: List<MomentReplayItem>,replayCount: Int){
            mReplayList.clear()
            shouldShowMore = replayCount >= maxVisibleCount

            mReplayList.addAll(replayList.subList(0, min(replayList.size,maxVisibleCount)))
            mObservable.notifyChanged()
        }

        internal fun generateReplayView(context: Context): ReplyView {
            return ReplyView(context)
        }

        fun handleReplayView(replyView: ReplyView, position: Int){
            val item = mReplayList[position]
            replyView.updateReplayItem(item)
            replyView.setReplayItemClickedListener {
                callback.replayItemClicked(it,item)
            }

            replyView.setMoreVisible(shouldShowMore
                    && position >= maxVisibleCount - 1)

            replyView.setReplayMoreClickedListener {
                callback.moreClicked(it,item)
            }
        }

        /**
         * 取消注册监听者
         */
        internal fun unregisterAdapterDataObserver(observer: AdapterDataObserver){
            mObservable.unregisterObserver(observer)
        }

        /**
         * 设置监听者
         */
        internal fun registerAdapterDataObserver(observer: AdapterDataObserver){
            mObservable.registerObserver(observer)
        }
    }

    /**
     * 适配器数据观察器
     * 一旦有观察者注册到观察器中，则在观察器调用了具体方法后
     * 会通知所有观察者进行对应操作
     */
    private class AdapterDataObservable: Observable<AdapterDataObserver>() {

        fun notifyChanged(){
            mObservers.forEach {
                it.onChanged()
            }
        }
    }

    /**
     * 数据变化观察者
     */
    private inner class ReplayDataObserver: AdapterDataObserver() {

        /**
         * 当数据发生改变后，重新进行图片绘制
         */
        override fun onChanged() {
            handleReplay()
        }
    }

    open class AdapterDataObserver{
        open fun onChanged(){
            // Do Nothing
        }
    }

    interface ReplayItemCallback{
        fun replayItemClicked(view: View,item: MomentReplayItem)
        fun moreClicked(view: View,item: MomentReplayItem)
    }


}